package top.bug.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import top.bug.blog.entity.dto.comments.CommentsAddRequest;
import top.bug.blog.entity.dto.comments.CommentsQueryRequest;
import top.bug.blog.entity.po.Comments;
import top.bug.blog.entity.vo.comments.CommentsVO;
import top.bug.blog.enums.ErrorCode;
import top.bug.blog.exception.BussinessException;
import top.bug.blog.mapper.CommentsMapper;
import top.bug.blog.service.CommentsService;
import top.bug.blog.service.SensitiveWordFilterService;
import top.bug.blog.utils.Ip2RegionUtil;
import top.bug.blog.utils.IpUtils;
import top.bug.blog.utils.UserAgentUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author <a href="https://github.com/jiusi66">九思.</a>
 * @email 10837907@qq.com
 * @from <a href="https://www.52bug.top">递归茶馆-www.52bug.top</a>
 * @description 评论实现类
 */
@Service
@Slf4j
public class CommentsServiceImpl extends ServiceImpl<CommentsMapper, Comments> implements CommentsService {
    @Resource
    private CommentsMapper commentsMapper;
    @Resource
    private SensitiveWordFilterService sensitiveWordFilterService;

    @Override
    public Page<CommentsVO> getCommentTreeByTarget(CommentsQueryRequest queryRequest) {
        int pageNum = queryRequest.getPageNum();
        int pageSize = queryRequest.getPageSize();
        // 1. 查询一级评论（根评论）
        Page<Comments> rootPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Comments> rootQuery = new LambdaQueryWrapper<Comments>()
                .eq(Comments::getTargetId, queryRequest.getTargetId())
                .eq(Comments::getTargetType, queryRequest.getTargetType())
                .eq(Comments::getRootId, "-1")
                // 已发布
                .eq(Comments::getStatus, "1")
                .orderByDesc(Comments::getCreateOn);
        Page<Comments> rootComments = commentsMapper.selectPage(rootPage, rootQuery);

        // 2. 获取所有根评论ID
        List<String> rootIds = rootComments.getRecords().stream()
                .map(Comments::getId)
                .collect(Collectors.toList());

        // 3. 查询所有非根评论（按root_id分组）
        Map<String, List<Comments>> replyMap;
        if (!rootIds.isEmpty()) {
            List<Comments> replies = commentsMapper.selectList(new LambdaQueryWrapper<Comments>()
                    .in(Comments::getRootId, rootIds)
                    .eq(Comments::getStatus, "1")
                    .eq(Comments::getIsDelete, "0")
                    .orderByAsc(Comments::getCreateOn));

            replyMap = replies.stream()
                    .collect(Collectors.groupingBy(Comments::getRootId));
        } else {
            replyMap = Collections.emptyMap();
        }

        // 4. 构建评论树
        List<CommentsVO> commentVOS = rootComments.getRecords().stream().map(root -> {
            CommentsVO rootVO = convertToVO(root);
            List<Comments> replies = replyMap.getOrDefault(root.getId(), Collections.emptyList());
            rootVO.setReplies(replies.stream().map(this::convertToVO).collect(Collectors.toList()));
            return rootVO;
        }).collect(Collectors.toList());

        // 5. 返回分页结果
        Page<CommentsVO> resultPage = new Page<>(rootPage.getCurrent(), rootPage.getSize(), rootPage.getTotal());
        resultPage.setRecords(commentVOS);
        return resultPage;
    }

    @Override
    public void addComment(CommentsAddRequest addRequest, HttpServletRequest request) {
        try {
            // 1. 敏感词过滤
            String filteredContent = sensitiveWordFilterService.filter(addRequest.getContent());
            String filteredNickname = sensitiveWordFilterService.filter(addRequest.getNickname());

            // 2. 检查是否需要审核
            boolean needReview = sensitiveWordFilterService.isReviewRequired();
            List<String> reviewWords = sensitiveWordFilterService.getReviewWords();

            // 2. 构建评论实体
            Comments comment = buildCommentEntity(addRequest, filteredContent, filteredNickname, request);

            // 4. 设置评论状态
            if (needReview) {
                // 设置为待审核状态
                comment.setStatus("0");
                log.info("评论内容包含审核词: {}, 已设置为待审核状态", reviewWords);
            } else {
                // 正常状态
                comment.setStatus("1");
            }

            // 3. 保存评论
            commentsMapper.insert(comment);

            // TODO: 审批通过时也需要更新父评论回复数
            // 4. 异步更新父评论回复数（只有审核通过的评论才计数）
            if (StringUtils.isNotBlank(addRequest.getParentId()) && !needReview) {
                updateParentReplyCount(addRequest.getParentId());
            }
        } catch (Exception e) {
            log.error("评论提交失败: {}", e.getMessage(), e);
            throw new BussinessException(ErrorCode.SYSTEM_ERROR, "评论提交失败，请稍后重试");
        } finally {
            // 清理ThreadLocal，防止内存泄漏
            sensitiveWordFilterService.clearReviewContext();
        }
    }

    /**
     * 构建评论实体
     */
    private Comments buildCommentEntity(CommentsAddRequest addRequest, String filteredContent,
                                        String filteredNickname, HttpServletRequest request) {
        Comments comment = new Comments();

        // 设置基本属性
        comment.setTargetId(addRequest.getTargetId());
        comment.setTargetType(addRequest.getTargetType());
        comment.setNickname(filteredNickname);
        comment.setEmail(addRequest.getEmail());
        comment.setWebsite(addRequest.getWebsite());
        comment.setContent(filteredContent);

        // 设置客户端信息
        setupClientInfo(comment, request);

        // 设置评论关系
        setupCommentRelation(comment, addRequest.getParentId());

        // 设置初始状态和计数
        // 默认待审核
        comment.setLikeNum(0);
        comment.setReplyNum(0L);
        // 非管理员评论
        comment.setIsAdmin("0");

        return comment;
    }

    /**
     * 设置客户端信息（IP、设备、浏览器等）
     */
    private void setupClientInfo(Comments comment, HttpServletRequest request) {
        try {
            // 获取客户端IP和地理位置
            String ipAddress = IpUtils.getClientIp(request);
            comment.setIpAddress(ipAddress);
            comment.setIpRegion(Ip2RegionUtil.getRegion(ipAddress));

            // 解析User-Agent信息
            String userAgentString = request.getHeader("User-Agent");
            UserAgentUtil.ClientInfo clientInfo = UserAgentUtil.parseUserAgent(userAgentString);

            comment.setDeviceType(clientInfo.getStandardDeviceType());
            comment.setBrowser(clientInfo.getBrowser() + " " + clientInfo.getBrowserVersion());
            comment.setOs(clientInfo.getOperatingSystem());

        } catch (Exception e) {
            log.warn("客户端信息解析失败: {}", e.getMessage());
            // 设置默认值
            comment.setIpAddress("0.0.0.0");
            comment.setIpRegion("未知");
            comment.setDeviceType("unknown");
            comment.setBrowser("Unknown");
            comment.setOs("Unknown");
        }
    }

    /**
     * 设置评论关系（父评论、根评论等）
     */
    private void setupCommentRelation(Comments comment, String parentId) {
        if (StringUtils.isBlank(parentId) || "-1".equals(parentId)) {
            // 一级评论
            comment.setParentId("-1");
            comment.setRootId("-1");
            comment.setReplyToNickname(null);
        } else {
            // 查询父评论
            Comments parentComment = commentsMapper.selectById(parentId);
            if (parentComment == null) {
                throw new BussinessException(ErrorCode.RESULT_DATA_NONE, "父评论不存在");
            }

            comment.setParentId(parentId);
            comment.setReplyToNickname(parentComment.getNickname());

            // 设置rootId：如果父评论是根评论，则rootId=父评论ID；否则继承父评论的rootId
            comment.setRootId("-1".equals(parentComment.getRootId()) ?
                    parentId : parentComment.getRootId());
        }
    }

    /**
     * 异步更新父评论回复数
     */
    @Async
    public void updateParentReplyCount(String parentId) {
        try {
            LambdaUpdateWrapper<Comments> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.setSql("reply_num = reply_num + 1")
                    .eq(Comments::getId, parentId);
            commentsMapper.update(null, updateWrapper);
            log.debug("成功更新父评论{}的回复数", parentId);
        } catch (Exception e) {
            log.error("更新父评论回复数失败: {}", e.getMessage());
        }
    }

    private CommentsVO convertToVO(Comments comment) {
        CommentsVO vo = new CommentsVO();
        BeanUtils.copyProperties(comment, vo);
        vo.setCreateOn(comment.getCreateOn());
        return vo;
    }
}